import React from 'react'
import PropTypes from 'prop-types'
import './GeoCheckboxList.scss'
import CampaignService from '../../services/CampaignService.js'
import CancelOnUnmount from '../../services/CancelOnUnmount.js'
import GeoService from '../../services/GeoService.js'

export default class GeoCheckboxList extends React.Component {
  static propTypes = {
    // Available ad formats
    items: PropTypes.arrayOf(
      PropTypes.shape({
        // Unique ID for the geo location
        geoId: PropTypes.string.isRequired,
        // Name of the city
        city: PropTypes.string.isRequired,
        // Name of the state
        state: PropTypes.string.isRequired
      })
    ),
    searchText: PropTypes.string.isRequired,
    // onToggleItem(itemToToggle) => void, should mark the item as selected
    onToggleItem: PropTypes.func,
    // getIsChecked(itemToCheck) => bool
    getIsChecked: PropTypes.func
  }

  constructor(props) {
    super(props)
    this.state = {
      // 用户输入的筛选条件
      searchText: '',
      // 用来记录哪些 城市 checkbox 是被选中的
      selectedGeoIds: [],
      // 存储查询的所有城市
      allGeos: [],
      // 从后台获取 选中的城市接口的 loading 效果
      isLoadingSelectedGeoIds: false,
      // 从后台获取 所有城市接口的 loading 效果
      isLoadingGeos: false
    }
  }

  // 组件挂载执行的方法
  componentDidMount() {
    this.initialCityLoad()
  }

  // 初始化，获取城市的信息
  initialCityLoad = () => {
    this.setState({
      isLoadingGeos: true,
      isLoadingSelectedGeoIds: true
    })

    // 获取所有城市的promise
    const refreshAllPromise = this.refreshAllCities()
    // 获取选中城市的 promise
    const getSelectedPromise = CampaignService.getSelectedGeoIds(
      this.props.campaignId
    ).then(selectedIds => {
      this.setState({
        selectedGeoIds: selectedIds,
        isLoadingSelectedGeoIds: false
      })
    })

    CancelOnUnmount.track(
      this,
      Promise.all([refreshAllPromise, getSelectedPromise]).catch(() => {
        this.setState({
          isError: true,
          isLoadingGeos: false,
          isLoadingSelectedGeoIds: false,
          onRetry: this.initialCityLoad
        })
      })
    )
  }

  renderItem = item => {
    return (
      <span>
        {item.city}, {item.state}
      </span>
    )
  }

  // 获取所有城市的信息
  refreshAllCities = () => {
    const promise = GeoService.getAllCities('city_name', false).then(
      allCities => {
        this.setState({
          allGeos: allCities,
          isLoadingGeos: false
        })
      }
    )
    CancelOnUnmount.track(this, promise)
    return promise
  }

  // 设置checkbox 选中
  handleToggleGeo = item => {
    const ids = this.state.selectedGeoIds

    if (ids.indexOf(item.geoId) >= 0) {
      this.setState({
        selectedGeoIds: ids.filter(id => id !== item.geoId)
      })
    } else {
      this.setState({
        selectedGeoIds: ids.concat(item.geoId)
      })
    }
  }

  // 用户输入过滤条件
  handleGeoSearchChanged(newSearch) {
    if (newSearch !== undefined) {
      this.setState({
        searchText: newSearch
      })
    } else {
      newSearch = this.state.searchText
    }
    // 如果用户没有输入任何内容，则显示所有的数据
    if (!newSearch || newSearch.length === 0) {
      this.refreshAllCities().catch(() => {
        this.setState({
          isError: true,
          onRetry: this.handleGeoSearchChanged
        })
      })
    } else {
      CancelOnUnmount.track(
        this,
        // 根据用户的输入，模拟筛选
        GeoService.getCitiesPaged(newSearch, 'city_name', false, 0, 100)
          .then(someCities => {
            this.setState({
              allGeos: someCities
            })
          })
          .catch(() => {
            this.setState({
              isError: true,
              onRetry: this.handleGeoSearchChanged
            })
          })
      )
    }
  }

  // 判断是否 查询的城市是否选中
  handleGetIsGeoChecked(item) {
    return this.state.selectedGeoIds.indexOf(item.geoId) >= 0
  }

  render() {
    let { searchText, allGeos } = this.state

    return (
      <div className="geocheckboxlist">
        <input
          type="search"
          placeholder="Search..."
          value={searchText}
          onChange={e => this.handleGeoSearchChanged.bind(this, e.target.value)}
        />
        <div className="geocheckboxlist__contents">
          {allGeos.length === 0 && <div>Loading...</div>}
          {allGeos.map(item => (
            <div key={item.geoId}>
              <label>
                <input
                  type="checkbox"
                  checked={this.handleGetIsGeoChecked.bind(this, item)}
                  onChange={this.handleToggleGeo.bind(this, item)}
                />
                {this.renderItem(item)}
              </label>
            </div>
          ))}
        </div>
      </div>
    )
  }
}

GeoCheckboxList.propTypes = {
  items: PropTypes.arrayOf(
    PropTypes.shape({
      geoId: PropTypes.string,
      name: PropTypes.string,
      state: PropTypes.string
    })
  ),
  onToggleItem: PropTypes.func,
  getIsChecked: PropTypes.func
}
